package com.ashlikun.pdfview

import com.ashlikun.pdfview.model.PagePart
import com.ashlikun.pdfview.util.PdfViewUtil
import kotlin.math.abs

internal class CacheManager(val config: PDFViewConfig) {
    private var caches = LRUCache(PdfViewUtil.CACHE_SIZE)
    val isCacheNeedZoom
        get() = config.isNeedZoomBitmap

    fun cacheBitmapSize(size: Int) {
        if (caches.capacity != size) {
            recycle()
            caches = LRUCache(size)
        }
    }


    inner class LRUCache(val capacity: Int) : MutableMap<String, PagePart> by object : LinkedHashMap<String, PagePart>(capacity, 0.75f, true) {
        override fun removeEldestEntry(eldest: MutableMap.MutableEntry<String, PagePart>): Boolean {
            // 当 map 的大小超过容量时，自动删除最老的条目
            return size > capacity
        }
    }

    fun set(part: PagePart) {
        synchronized(caches) {
            if (caches.containsKey(part.getKey(isCacheNeedZoom))) {
                // 移除旧数据
                caches.remove(part.getKey(isCacheNeedZoom))?.bitmap?.recycle()
            }
            // 添加
            caches[part.getKey(isCacheNeedZoom)] = part
        }
    }

    fun get(page: Int, zoom: Float) = synchronized(caches) {
        if (!isCacheNeedZoom) caches["$page"]
        else caches["$page-$zoom"]
    }

    /**
     * 获取缓存
     * 如果当前页缩放后未及时获取数据，那么就先显示之前的当前页数据
     */
    fun getFindZoom(page: Int, zoom: Float) = synchronized(caches) {
        if (!isCacheNeedZoom) return@synchronized caches["$page"]
        var zp = caches["$page-$zoom"]
        if (zp == null) {
            //查找当前页全部数据
            val pageAll = caches.filter { it.key.startsWith("$page-") }
            val key = pageAll.keys.minByOrNull { abs(it.split("-").last().toFloat() - zoom) }
            if (key != null) {
                zp = pageAll[key]
            }
        }
        if (zp != null) {
//            if (PdfViewUtil.DEBUG_MODE) PdfViewUtil.logi("getFindZoom   page = $page  zoom = $zoom    key${zp!!.getKey()} ")
        }
        zp
    }

    /**
     * 如果已包含所描述的PagePart，则返回true
     */
    fun contains(page: Int, zoom: Float) = synchronized(caches) {
        if (!isCacheNeedZoom) return@synchronized caches.containsKey("$page")
        var cacheKey = if (caches.containsKey("$page-$zoom")) "$page-$zoom" else null
        if (cacheKey == null) {
            //查找当前页全部数据
            val pageAll = caches.filter { it.key.startsWith("$page-") }
            cacheKey = pageAll.keys.find {
                val cZoom = it.split("-").last().toFloat()
                val diff = cZoom - zoom
                //前后0.2都可以  如1.5    1.3-1.7 都可以
                abs(diff) <= 0.2
            }
        }
        if (cacheKey != null) {
//            if (PdfViewUtil.DEBUG_MODE) PdfViewUtil.logi("Cache contains   page = $page  zoom = $zoom    cacheData$cacheKey ")
        }
        return@synchronized cacheKey != null
    }


    fun recycle() {
        synchronized(caches) {
            caches.forEach {
                it.value.bitmap.recycle()
            }
            caches.clear()
        }
    }
}
